package com.hllxd.hism.passport.login.gateway.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hllxd.hism.passport.login.gateway.exception.BusinessException;
import com.hllxd.hism.passport.login.gateway.config.PassportProperties;
import com.hllxd.hism.passport.login.gateway.constant.PassportConstants;
import com.hllxd.hism.passport.login.gateway.error.ErrorCode;
import com.hllxd.hism.passport.login.gateway.error.PassportErrorCode;
import com.hllxd.hism.passport.login.gateway.model.AccessToken;
import com.hllxd.hism.passport.login.gateway.model.LogOnDynamicCodeResponse;
import com.hllxd.hism.passport.login.gateway.model.UserEntity;
import com.hllxd.hism.passport.login.gateway.service.PassportService;
import com.hllxd.hism.passport.login.gateway.util.CookieUtil;
import com.hllxd.hism.passport.login.gateway.util.ResultUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;


/**
 * Personal Computer PC端登录对应的 @Controller
 * @author lixiyong01
 * @date 2021.11.07
 */
@RestController
@Slf4j
public class PcLoginController {
    @Autowired
    PassportProperties passportProperties;
    @Autowired private PassportService passportService;

    public static String generateResult(ErrorCode errorCode) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code", errorCode.getCode());
        jsonObject.put("message", errorCode.getMessage());
        jsonObject.put("success", errorCode.isSuccess());
        return jsonObject.toJSONString();
    }
    public static String generateResultFromPassportError(String code, String msg) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code", code);
        jsonObject.put("message", msg);
        jsonObject.put("success", false);
        return jsonObject.toJSONString();
    }

    protected String generateSuccessResult(Object data) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code", "000");
        jsonObject.put("message", "成功");
        jsonObject.put("success", true);
        jsonObject.put("data", data);
        return jsonObject.toJSONString();
    }

    /**
     * WEB PC-Send dynamic code string.
     * 发送动态码
     * @return the string
     */
    @ResponseBody @RequestMapping(value = "/sendDynamicCode", method = RequestMethod.POST, produces = "application/json;" + "charset=UTF-8")
    public Object sendDynamicCode(@RequestParam String phoneNumber) throws IOException {

        try {
            log.info("phone number: {}.", phoneNumber);
            passportService.sendDynamicCode(phoneNumber, 0);
        }
        catch (BusinessException e) {
            return generateResultFromPassportError(e.code, e.msg);
        }
        return ResultUtils.result("验证码下发成功");
    }

    public static class DynamicCodeDto {
        public String phoneNumber;
    }

    @RequestMapping(value = "/sendDynamicCode2", method = RequestMethod.POST)
    public Object sendDynamicCode2(@RequestBody DynamicCodeDto dto) throws IOException {

        try {
            log.info("phone number: {}.", dto.phoneNumber);
            passportService.sendDynamicCode(dto.phoneNumber, 0);
        }
        catch (BusinessException e) {
            return generateResultFromPassportError(e.code, e.msg);
        }
        return ResultUtils.result("验证码下发成功");
    }

    @RequestMapping(value = "/addUser.do", method = RequestMethod.POST)
    public Object addUser(@RequestBody UserEntity dto) throws IOException {

        try {
            log.info("user entity: {}.", JSON.toJSONString(dto));
            passportService.addUser(dto);
        }
        catch (BusinessException e) {
            return generateResultFromPassportError(e.code, e.msg);
        }
        return ResultUtils.result("注册成功");
    }


    /**
     * WEB-PC 通过动态码登录
     * @param phoneNumber 电话号码
     * @param dynamicCode 动态码
     * @param plat 0-WEB（默认） 1-移动
     * @param redirectUrl 重定向URL
     * @param request 请求参数
     * @param response 返回
     * @return 返回
     * @throws Exception
     */
    @ResponseBody
    @RequestMapping(value = "/loginAjaxDynamicCode", method = RequestMethod.POST, produces = "application/json;" + "charset=UTF-8")
    public Object logOnDynamicCode(
            @RequestParam(value = "phoneNumber", required = true) String phoneNumber,
            @RequestParam(value = "dynamicCode", required = true) String dynamicCode,
            @RequestParam(value = "plat", required = false, defaultValue = "0") int plat,
            @RequestParam(value = "redirectURL", required = true) String redirectUrl, HttpServletRequest request, HttpServletResponse response)
        throws Exception {

        log.info("params is phone: {}, dynamic code: {}, plat: {}, redirect url: {}", phoneNumber, dynamicCode, plat, redirectUrl);
        LogOnDynamicCodeResponse codeResponse;
        try {
            codeResponse = passportService.logOnDynamicCode(phoneNumber, dynamicCode, plat);
        } catch (BusinessException e) {
            return generateResultFromPassportError(e.code, e.msg);
        }
        log.info("check success, will set cookie.");
        AccessToken accessToken = JSON.parseObject(codeResponse.getAccessTokenJson(), AccessToken.class);
        Cookie cookie = new Cookie(PassportConstants.PASSPORT_ACCESS_TOKEN_COOKIE_KEY, accessToken.getAccessToken());
        cookie.setMaxAge(PassportConstants.ACCESS_TOKEN_EXPIRE_TIME);
        CookieUtil.setCookieDomain(cookie, passportProperties.getCookieDomain());
        response.addCookie(cookie);
        log.info("set cookie success. {}", cookie);

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("redirectUrl", redirectUrl);
        return generateSuccessResult(jsonObject);
    }

    public static class LogonDto {
        public String phoneNumber;
        public String dynamicCode;
        public Integer plat=0;
        public String redirectUrl;
    }
    @RequestMapping(value = "/loginAjaxDynamicCode2", method = RequestMethod.POST)
    public Object logOnDynamicCode2(
            @RequestBody LogonDto dto, HttpServletRequest request, HttpServletResponse response)
            throws Exception {

        log.info("params is phone: {}, dynamic code: {}, plat: {}, redirect url: {}", dto.phoneNumber, dto.dynamicCode, dto.plat, dto.redirectUrl);
        LogOnDynamicCodeResponse codeResponse;
        try {
            codeResponse = passportService.logOnDynamicCode(dto.phoneNumber, dto.dynamicCode, dto.plat);
        } catch (BusinessException e) {
            return generateResultFromPassportError(e.code, e.msg);
        }
        log.info("check success, will set cookie.");
        AccessToken accessToken = JSON.parseObject(codeResponse.getAccessTokenJson(), AccessToken.class);
        Cookie cookie = new Cookie(PassportConstants.PASSPORT_ACCESS_TOKEN_COOKIE_KEY, accessToken.getAccessToken());
        cookie.setMaxAge(PassportConstants.ACCESS_TOKEN_EXPIRE_TIME);
        CookieUtil.setCookieDomain(cookie, passportProperties.getCookieDomain());
        response.addCookie(cookie);
        log.info("set cookie success. {}", cookie);

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("redirectUrl", dto.redirectUrl);
        return generateSuccessResult(jsonObject);
    }

    //    @ResponseBody
    //    @RequestMapping(value = "/loginUserID", method = RequestMethod.POST
    //            , produces = "application/json;" + "charset=UTF-8")
    //    public String loginUserID(@RequestParam(value = "userID", required = true) String
    //                                      userID,
    //                              // 默认是0，web登录, 见Plat
    //                              @RequestParam(value = "plat", required = false, defaultValue = "0") int plat,
    //                              HttpServletRequest request, HttpServletResponse response) throws Exception {
    //        LogOnResult logOnResult;
    //        try {
    //            logOnResult = passportClient.logOnUserID(userID,plat, request);
    //        } catch (UserAuthenticateFailedException e) {
    //            return PassportUtil.generateResultFromPassportError(PassportErrorCode
    //                    .USER_AUTHENTICATE_FAILED, null);
    //        } catch (DynamicCodeVerificationCountOutOfLimitException e) {
    //            return PassportUtil.generateResultFromPassportError(PassportErrorCode
    //                    .DYNAMIC_CODE_VERIFICATION_COUNT_OUT_LIMIT, null);
    //        }
    //
    //        Cookie loginCookie = new Cookie(PassportConstants.PASSPORT_ACCESS_TOKEN_COOKIE_KEY, logOnResult.getTokenValue());
    //        loginCookie.setMaxAge(PassportConstants.ACCESS_TOKEN_EXPIRE_TIME);
    //        passportClientUtil.setCookieDomain(loginCookie);
    //        response.addCookie(loginCookie);
    //
    //        JSONObject jsonObject = new JSONObject();
    //        jsonObject.put("accesstoken", logOnResult.getTokenValue());
    //        return generateSuccessResult(jsonObject);
    //    }

    private String extractHostFromLoginUrl(String loginUrl) {
        String replace = loginUrl.replace("/login", "");
        return replace;
    }

    @ResponseBody
    @RequestMapping(value = "/logOnQRCode", produces = "application/json;" + "charset=UTF-8")
    public Object logOnQRCode(@RequestParam String content,
        @RequestParam String accessToken) throws IOException {

        LogOnQRCodeResult result = passportService.logOnQrCode(content, accessToken);
        if (result.isResult()) {
            return ResultUtils.result("扫码登录成功");
        } else {
            if (result.getErrorCode() == null) {
                throw new IllegalStateException("错误码异常!");
            }
            return ResultUtils.errorResult(result.getErrorCode().getCode(), result.getErrorCode().getMessage());
        }
    }

    @ResponseBody @RequestMapping(value = "/getQRCode", method = RequestMethod.POST, produces = "application/json;" + "charset=UTF-8")
    public Object getQRCode(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String qrCode = passportService.getQRCode();

        JSONObject resultQRCode = new JSONObject();
        resultQRCode.put("qrCode", qrCode);
        resultQRCode.put("host", extractHostFromLoginUrl(passportProperties.getLoginUrl()));
        resultQRCode.put("isMis", true);

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("content", resultQRCode.toJSONString());

        return ResultUtils.result(jsonObject);
    }

    @ResponseBody @RequestMapping(value = "/getToken", method = RequestMethod.POST, produces = "application/json;" + "charset=UTF-8")
    public Object getToken(@RequestParam String content, @RequestParam(value = "redirectURL", required = true) String redirectUrl,
        HttpServletRequest request, HttpServletResponse response) throws Exception {
        String accessToken = passportService.getToken(content);

        if (!StringUtils.isEmpty(accessToken)) {
            Cookie loginCookie = new Cookie(PassportConstants.PASSPORT_ACCESS_TOKEN_COOKIE_KEY, accessToken);
            loginCookie.setMaxAge(PassportConstants.ACCESS_TOKEN_EXPIRE_TIME);
            CookieUtil.setCookieDomain(loginCookie, passportProperties.getCookieDomain());
            response.addCookie(loginCookie);

            JSONObject jsonObject = new JSONObject();
            jsonObject.put("redirectUrl", redirectUrl);
            return ResultUtils.result(jsonObject);
        } else {
            return ResultUtils.errorResult(PassportErrorCode.NOT_YET_SCAN_QR_CODE.getCode(), PassportErrorCode.NOT_YET_SCAN_QR_CODE.getMessage());
        }
    }

    /**
     * 获得验证码
     * @param request http
     * @param response http
     * @throws IOException
     */
    @ResponseBody
    @RequestMapping(value = "/getVerifyCode", produces = "application/json;charset=UTF-8")
    public void getVerifyCode(HttpServletRequest request, HttpServletResponse response) throws IOException{
        VerifyCode vc=new VerifyCode();
        //获得图片
        BufferedImage image=vc.getImage();
        //将验证码内容放在域对象里面
        request.getSession().setAttribute("verify_code",vc.getText());
        // 写入结果
        VerifyCode.output(image, response.getOutputStream());
    }

    public static class LogonAccountDto {
        public String username;
        public String password;
        public String verifyCode;
        public Integer plat=0;
        public String redirectUrl;
    }
    @RequestMapping(value = "/loginAccountCode", method = RequestMethod.POST)
    public Object loginAccountCode(
            @RequestBody LogonAccountDto dto, HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        String sessionCode = (String) request.getSession().getAttribute("verify_code");
        String paramCode = dto.verifyCode;
        if(StringUtils.isEmpty(dto.verifyCode) || !paramCode.equalsIgnoreCase(sessionCode)){
            return generateResultFromPassportError("002", "验证码错误！");
        }
        VerifyCode vc=new VerifyCode();
        request.getSession().setAttribute("verify_code",vc.resetVerifyCode());

        LogOnDynamicCodeResponse codeResponse;
        try {
            codeResponse = passportService.logOnAccountCode(dto.username, dto.password, dto.plat);
        } catch (BusinessException e) {
            return generateResultFromPassportError(e.code, e.msg);
        }
        log.info("check success, will set cookie.");
        AccessToken accessToken = JSON.parseObject(codeResponse.getAccessTokenJson(), AccessToken.class);
        Cookie cookie = new Cookie(PassportConstants.PASSPORT_ACCESS_TOKEN_COOKIE_KEY, accessToken.getAccessToken());
        cookie.setMaxAge(PassportConstants.ACCESS_TOKEN_EXPIRE_TIME);
        CookieUtil.setCookieDomain(cookie, passportProperties.getCookieDomain());
        response.addCookie(cookie);
        log.info("set cookie success. {}", cookie);

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("redirectUrl", dto.redirectUrl);
        return generateSuccessResult(jsonObject);
    }
}
